package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.mac.MacEngine;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.zzyl.dto.UserLoginRequestDto;
import com.zzyl.entity.customer.Member;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.MemberMapper;
import com.zzyl.properties.JwtTokenProperties;
import com.zzyl.service.WechatService;
import com.zzyl.utils.JwtUtil;
import com.zzyl.vo.LoginVo;
import com.zzyl.vo.LolnameList;
import lombok.RequiredArgsConstructor;
import org.apache.coyote.http11.Constants;
import org.apache.ibatis.annotations.Select;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class WechatServiceImpI implements WechatService {
    private LolnameList list = new LolnameList();
    private List<String> DEFAULT_NICKNAME_PREFIX = list.getHeroes();
    @Value("${zzyl.wechat.appId}")
    private String appId;
    @Value("${zzyl.wechat.appSecret}")
    private String appSecret;
    @Autowired
    private JwtTokenProperties token;
    @Autowired
    private  WechatService wechatService;
    @Autowired
    private MemberMapper memberMapper;
    
    @Override
    public String getWxOpenId(String code) {
/*        https://api.weixin.qq.com/sns/jscode2session 是微信提供的API接口之一，用于通过小程序的登录凭证（code）换取用户的openid和session_key。这个接口是微信小程序开发中非常重要的一部分，因为它允许开发者获取到用户的唯一标识（openid），进而可以进行用户身份的识别和数据的关联。
        当你访问这个URL并提供了正确的参数（包括appid、secret、js_code和grant_type）时，微信服务器会返回一个JSON格式的响应，其中包含了以下信息：
        openid：用户的唯一标识符。
        session_key：会话密钥，用于后续的业务逻辑，比如解密用户数据。*/
        String url = "https://api.weixin.qq.com/sns/jscode2session";
        System.out.println("js_code:"+code);
        System.out.println("appId:"+appId);
        System.out.println("appSecret:"+appSecret);
        Map<String,Object> params = new HashMap<>();
        params.put("appid", appId);//AppID(小程序ID)
        params.put("secret", appSecret);//AppSecret(小程序密钥)
        params.put("js_code", code);//唯一凭证
        // 发送GET请求 相当于拼接 url+params
        String json = HttpUtil.get(url,params);
        //错误信息，所以下面判断，成功带openid
//        {"errcode":41002, 
//         "errmsg":"appid missing, " 
//          "rid: 672db874-36759211-39eaf485"}
        System.out.println(json);
//这一步代表了我们把返回的json字符串转换成json对象，方便我们做出判断以及拿值
        JSONObject entries = JSONUtil.parseObj(json);
        if (entries.containsKey("errcode")) {
            //这一步直接失败，抛出异常
            throw new BaseException(BasicEnum.GET_OPENID_ERROR);
        }
        //成功返回openid给方法getWxOpenId
        return entries.getStr("openid");
    }
    @Override
    public String getWxAccessToken() {
        String url = "https://api.weixin.qq.com/cgi-bin/token";
        Map<String, Object> params = Map.of("grant_type","client_credential","appid",appId,"secret",appSecret);
        String jsonBody = HttpUtil.get(url, params);
        JSONObject entries = JSONUtil.parseObj(jsonBody);
        System.out.println(entries.toString());
        if (!entries.containsKey("access_token")) {
            throw new BaseException(BasicEnum.GET_TOKEN_ERROR);
        }
        return entries.getStr("access_token");
    }

    @Override
    public String gettWxPhoneNumber(String access_token, String code, String openid) {
        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+access_token;
        //1. 封装请求参数发送请求访问微信服务器
        Map<String, Object> params = Map.of("code", code, "openid", openid);
        String jsonBody = HttpUtil.post(url, JSONUtil.toJsonStr(params));
        //2. 解析响应数据
        JSONObject jsonObject = JSONUtil.parseObj(jsonBody);
        System.out.println(jsonObject);
        if (!jsonObject.containsKey("phone_info")) {
            throw new BaseException(BasicEnum.GET_PHONE_ERROR);
        }
        JSONObject phoneInfo = jsonObject.getJSONObject("phone_info");
        return phoneInfo.getStr("phoneNumber");
    }

    @Override
    public LoginVo login(UserLoginRequestDto userLoginRequestDto) {
       if (BeanUtil.isEmpty(userLoginRequestDto)){
           throw new BaseException(BasicEnum.WX_LOGIN_PARAMS_ERROR);
       }
      
        String wxOpenId = wechatService.getWxOpenId(userLoginRequestDto.getCode());
        String wxAccessToken = wechatService.getWxAccessToken();
        String wxPhoneNumber = wechatService.gettWxPhoneNumber(wxAccessToken, userLoginRequestDto.getPhoneCode(), wxOpenId);
         Member member = memberMapper.login(wxOpenId);
        if (BeanUtil.isEmpty(member)){
            member = member.builder()
                    .phone(wxPhoneNumber).name(getNickName(wxPhoneNumber)).openId(wxOpenId).avatar("https://inews.gtimg.com/om_bt/OGlQWfsaAoKkuCcMZ2o9IVEPqd-72DQy5EAN02XBHUwfYAA/641")
                    .gender(0).build();
            memberMapper.save(member);
        }else {
            if (!StrUtil.equals(member.getPhone(),wxPhoneNumber)){
                member.setPhone(wxPhoneNumber);
                memberMapper.updateopp(member);
            }
            
        }
        Map<String,Object> claims = new HashMap<>();
        claims.put("id",member.getId());
        claims.put("name", member.getName());
         String jwt = JwtUtil.createJWT(token.getBase64EncodedSecretKey(), getOffsetDays(token.getTtl()),claims);
         LoginVo loginVo = LoginVo.builder().token(jwt).nickName(member.getName()).build();
        return loginVo;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    private int getOffsetDays(Integer ttl){
        Long days = Convert.convertTime(ttl,TimeUnit.SECONDS, TimeUnit.DAYS);
        return days.intValue();
    }
    private String getNickName(String wxPhoneNumber){
        String prefix = DEFAULT_NICKNAME_PREFIX.get(RandomUtil.randomInt(DEFAULT_NICKNAME_PREFIX.size()));
        String suffix = StrUtil.subSuf(wxPhoneNumber, 7);
        return prefix + suffix;
    }
}
